package com.qfedu.servlet;

import com.qfedu.annotation.Controller;
import com.qfedu.annotation.RequestMapping;
import com.qfedu.utils.ClassUtils;
import org.apache.commons.lang.StringUtils;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class MyDispatcherServlet extends HttpServlet {

    private ConcurrentHashMap<String,Object> beans=new ConcurrentHashMap<>();
    private ConcurrentHashMap<String,Object> urlBeans=new ConcurrentHashMap<>();
    private ConcurrentHashMap<String,String> urlMethodsBeans=new ConcurrentHashMap<String,String>();


    @Override
    public void init() throws ServletException {
        // 定义一个扫包的路径，进行扫包获取全部的类，并放入集合
        List<Class<?>> classes = ClassUtils.getClasses("com.qfedu.controller");
        try {
            //找到有Controller注解的类并实例化放入beans集合中
            findClassAnnotation(classes);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //将url映射和方法进行关联
        hanlderMapping();

    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=UTF-8");
        doPost(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("进入servlet");
        String requestURI = req.getRequestURI();
        if(StringUtils.isEmpty(requestURI)){
            return;
        }
        Object object = urlBeans.get(requestURI);
        if(object==null){
            resp.getWriter().print("not found 404 url");
            return;
        }
        String urlName = urlMethodsBeans.get(requestURI);
        if(StringUtils.isEmpty(urlName)){
            resp.getWriter().print("not found method");
        }

        String methodInvoke = (String) methodInvoke(object, urlName);
        resp.getWriter().print(methodInvoke);

        resp.getWriter().write("没有问题，可以进入");
    }

    public Object methodInvoke(Object object,String urlName){
        Class<?> aClass = object.getClass();
        try {
            Method method = aClass.getMethod(urlName);
            Object result = method.invoke(object);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public void findClassAnnotation(List<Class<?>> listClass) throws IllegalAccessException, InstantiationException {
        for (Class<?> aClass : listClass) {
            Controller declaredAnnotation = aClass.getDeclaredAnnotation(Controller.class);
            if(declaredAnnotation!=null){
                String simpleName = ClassUtils.toLowerCaseFirstOne(aClass.getSimpleName());
                Object newInstance = aClass.newInstance();
                beans.put(simpleName,newInstance);
            }
        }
    }
    public void hanlderMapping(){
        for (Map.Entry<String, Object> entry : beans.entrySet()) {
            Object object = entry.getValue();
            Class<?> aClass = object.getClass();
            //看这个类是否有RequestMapping 注解
            RequestMapping requestMappingAnnotation = aClass.getDeclaredAnnotation(RequestMapping.class);
            String baseUrl="";
            if(requestMappingAnnotation!=null){
                //获取类上Requestmapping注解的值
                baseUrl ="/"+ requestMappingAnnotation.value();
            }
            Method[] declaredMethods = aClass.getDeclaredMethods();
            for (Method method : declaredMethods) {
                //看这个类中的方法是否有Rquest Mapping这个注解
                RequestMapping declaredAnnotation = method.getDeclaredAnnotation(RequestMapping.class);
                if(declaredAnnotation!=null){
                    String methodUrl=baseUrl+"/"+declaredAnnotation.value();
                    //
                    urlBeans.put(methodUrl,object);
                    urlMethodsBeans.put(methodUrl,method.getName());
                }
            }
        }
    }


}
